package com.android.router.core;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.core.app.ActivityCompat;

import com.android.annotation.entity.RouterEntity;
import com.android.router.core.utils.ClassUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Set;

public class AndroidRouter {
    private static final String TAG = "AndroidRouter";
    private static final String ROUTER_PACKAGE_NAME = "com.hwm.android.router";
    private static final String SDK_NAME = "AndroidRouter";
    private static final String SEPARATOR = "_";
    private static final String SUFFIX_ALL_GROUP = "All" + SEPARATOR + "Group";

    private static final AndroidRouter mInstance = new AndroidRouter();

    private Application application;

    private AndroidRouter() {

    }

    public void init(Application context) {
        application = context;
        try {
            loadRouters();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static AndroidRouter getInstance() {
        return mInstance;
    }

    /**
     * 取出编译时扫描获取的所有路由信息
     * @throws PackageManager.NameNotFoundException
     * @throws InterruptedException
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    private void loadRouters() throws PackageManager.NameNotFoundException, InterruptedException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获得所有 apt生成的路由类的全类名 (路由表)
        Set<String> routerMap = ClassUtils.getFileNameByPackageName(application, ROUTER_PACKAGE_NAME);
        for (String className : routerMap) {
            if (className.startsWith(ROUTER_PACKAGE_NAME + "." + SDK_NAME + SEPARATOR + SUFFIX_ALL_GROUP)) {
                //root中注册的是分组信息 将分组信息加入仓库中
                ((IRouterAllGroup) Class.forName(className).getConstructor().newInstance()).loadRouters(RouterDataStore.allGroupRouter);
            }
        }
        for (Map.Entry<String, Class<? extends IRouterGroup>> stringClassEntry : RouterDataStore.allGroupRouter.entrySet()) {
            Log.d(TAG, "Root映射表[ " + stringClassEntry.getKey() + " : " + stringClassEntry.getValue() + "]");
        }
    }

    public Postcard build(String path) {
        if (TextUtils.isEmpty(path)) {
            throw new RuntimeException("路由地址无效!");
        } else {
            return build(path, extractGroup(path));
        }
    }

    public Postcard build(String path, String group) {
        if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
            throw new RuntimeException("路由地址无效!");
        } else {
            return new Postcard(path, group);
        }
    }

    /**
     * 获得组别
     *
     * @param path
     * @return
     */
    private String extractGroup(String path) {
        if (TextUtils.isEmpty(path) || !path.startsWith("/")) {
            throw new RuntimeException(path + " : 不能提取group.");
        }
        String defaultGroup = path.substring(1, path.indexOf("/", 1));
        if (TextUtils.isEmpty(defaultGroup)) {
            throw new RuntimeException(path + " : 不能提取group.");
        } else {
            return defaultGroup;
        }
    }

    public Object navigation(final Context context, final Postcard postcard, final int requestCode) {
        prepareCard(postcard);
        switch (postcard.getType()) {
            case ACTIVITY:
                Context currentContext = null == context ? application : context;
                Intent intent = new Intent(currentContext, postcard.getDestination());
                intent.putExtras(postcard.getExtras());
                int flags = postcard.getFlags();
                if (-1 != flags) {
                    intent.setFlags(flags);
                } else if (!(currentContext instanceof Activity)) {
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }
                if (requestCode > 0) {
                    ActivityCompat.startActivityForResult((Activity) currentContext, intent,
                            requestCode, postcard.getExtras());
                } else {
                    ActivityCompat.startActivity(currentContext, intent, postcard.getExtras());
                }
                break;
            case IMODULE:
                return postcard.getModule();
            default:
                break;
        }
        return null;
    }

    /**
     * 准备卡片
     *
     * @param card
     */
    private void prepareCard(Postcard card) {
        RouterEntity routerEntity = RouterDataStore.groupRouter.get(card.getPath());
        if (null == routerEntity) {
            Class<? extends IRouterGroup> routerGroup = RouterDataStore.allGroupRouter.get(card.getGroup());
            if (null == routerGroup) {
                throw  new RuntimeException("没找到对应路由：分组=" + card.getGroup() + "   路径=" + card.getPath());
            }
            IRouterGroup iRouterGroupInstance;
            try {
                iRouterGroupInstance = routerGroup.getConstructor().newInstance();
            } catch (Exception e) {
                throw new RuntimeException("路由分组映射表记录失败.", e);
            }
            iRouterGroupInstance.loadRouters(RouterDataStore.groupRouter);
            //已经准备过了就可以移除了 (不会一直存在内存中)
            RouterDataStore.allGroupRouter.remove(card.getGroup());
            //再次进入 else
            prepareCard(card);
        } else {
            //类 要跳转的activity 或IService实现类
            card.setDestination(routerEntity.getDestination());
            card.setType(routerEntity.getType());
            switch (routerEntity.getType()) {
                case IMODULE:
                    Class<?> destination = routerEntity.getDestination();
                    IModule module = RouterDataStore.services.get(destination);
                    if (null == module) {
                        try {
                            module = (IModule) destination.getConstructor().newInstance();
                            RouterDataStore.services.put(destination, module);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    card.setModule(module);
                    break;
                default:
                    break;
            }
        }
    }

}
